import {Body, Controller, Get, HttpStatus, Post, Query, Res, Headers} from '@nestjs/common';
import {Response} from 'express';
import {CommonResponseDto} from '../dto/common.response.dto';
import {ResCode, UserStatus} from '../common/constants';
import {UserListService} from '../service/user.list.service';
import {OperateLogService} from '../service/operate.log.service';
import {formatTime, uuid} from "../common/utils";
import {decrypt, encrypt, generateRandomTokenBase64, getModelConfigList} from "../common/common";
import {CommonRedisService} from "../service/common.redis.service";
import AppConfig from "../../config/app.config";
import {PaginationDataDto} from "../dto/pagination.data.dto";


@Controller('api/user')
export class UserListController {
    constructor(private readonly commonRedisService: CommonRedisService,
                private readonly userListService: UserListService,
                private readonly operateLogService: OperateLogService) {}

    @Post('/list')
    async getAllList(@Body() body: {userAccount: string, status: UserStatus, orderProp: string, order: string, pageIndex: number, pageSize: number}, @Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        if (!body.pageIndex || body.pageIndex < 1) {
            body.pageSize = 1
        }
        if (!body.pageSize || body.pageSize < 1) {
            body.pageSize = 10
        }
        let order = null
        if (body.order === 'ascending') {
            order = 'ASC'
        }
        if (body.order === 'descending') {
            order = 'DESC'
        }
        try {
            const data = await this.userListService.getAllUserListByCondition(body.userAccount, body.status, body.orderProp, order, body.pageIndex, body.pageSize)
            if (data && data.length === 2) {
                const pageTotal = Math.ceil(data[1]/body.pageSize);
                return new CommonResponseDto(ResCode.OK, 'success', new PaginationDataDto(
                    body.pageIndex, body.pageSize, pageTotal, data[1], data[0]
                ))
            }
            return new CommonResponseDto(ResCode.ERROR, '查询失败')
        } catch(e){
            return new CommonResponseDto(ResCode.ERROR, '获取数据异常')
        }
    }

    @Get('/get')
    async getOne(@Query('userId') userId: string, @Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        try {
            const data = await this.userListService.getOneById(userId)
            delete data.userPassword
            return new CommonResponseDto(ResCode.OK, 'success', data)
        } catch(e){
            return new CommonResponseDto(ResCode.ERROR, '获取数据异常')
        }
    }

    @Post('/create')
    async createOne(@Body() params: {userAccount: string, userPassword: string, contact: string, remark: string}, @Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        if (!params.userAccount || !params.userPassword) {
            return new CommonResponseDto(ResCode.ERROR, '缺少参数')
        }
        try {
            const existUser = await this.userListService.getOneByAccount(params.userAccount)
            if (existUser) {
                return new CommonResponseDto(ResCode.ERROR, '账号已存在')
            }
            const userId = uuid(32)
            const time = new Date().getTime()
            const createDate = formatTime(time)
            await this.userListService.createOne({
                userId,
                userAccount: params.userAccount,
                userPassword: params.userPassword,
                contact: params.contact || '',
                remark: params.remark || '',
                createDate,
                balance: '0',
                status: UserStatus.NORMAL,
            })
            const token = generateRandomTokenBase64(128)
            await this.commonRedisService.set(AppConfig.ApiHeaderKey + '_' + userId, token, AppConfig.ApiTokenExpireSec)
            return new CommonResponseDto(ResCode.OK, 'success', {
                userId,
                userAccount: params.userAccount,
                contact: params.contact || '',
                createDate,
                balance: 0,
                status: UserStatus.NORMAL,
            })
        } catch(e){
            console.log(e)
            return new CommonResponseDto(ResCode.ERROR, '创建用户异常')
        }
    }

    @Post('/password-reset')
    async updatePassword(@Body() params: {userId: string, userPassword: string,}, @Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        if (!params.userId || !params.userPassword) {
            return new CommonResponseDto(ResCode.ERROR, '缺少参数')
        }
        try {
            const result = await this.userListService.editPassword(params.userId, params.userPassword)
            if (result) {
                return new CommonResponseDto(ResCode.OK, 'success')
            }
            return new CommonResponseDto(ResCode.ERROR, '更新失败')
        } catch(e){
            return new CommonResponseDto(ResCode.ERROR, '更新异常')
        }
    }

    @Post('/info-update')
    async updateInfo(@Body() params: {userId: string, contact: string, remark: string}, @Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        params.contact = params.contact || ''
        if (!params.userId) {
            return new CommonResponseDto(ResCode.ERROR, '缺少参数')
        }
        try {
            const result = await this.userListService.editInfo(params.userId, params.contact, params.remark)
            if (result) {
                return new CommonResponseDto(ResCode.OK, 'success')
            }
            return new CommonResponseDto(ResCode.ERROR, '更新失败')
        } catch(e){
            return new CommonResponseDto(ResCode.ERROR, '更新异常')
        }
    }

    @Post('/recharge')
    async recharge(@Headers() headers: Record<string, string>, @Body() params: {userId: string, amount: number,}, @Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        if (!params.userId || !params.amount) {
            return new CommonResponseDto(ResCode.ERROR, '缺少参数')
        }
        try {
            await this.userListService.exeRecharge(params.userId, params.amount)
            this.operateLogService.createOne({
                id: uuid(32),
                userId: decrypt(headers[AppConfig.AdminHeaderKey], AppConfig.AdminSecretKey).split('_')[0],
                toUserId: params.userId,
                time: formatTime(new Date().getTime()),
                type: 'recharge',
                desc: `${params.amount}`
            })
            return new CommonResponseDto(ResCode.OK, 'success')
        } catch(e){
            return new CommonResponseDto(ResCode.ERROR, '充值异常')
        }
    }

    @Post('/status-update')
    async updateStatus(@Body() params: {userId: string, status: UserStatus,}, @Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        if (![UserStatus.NORMAL, UserStatus.DELETED, UserStatus.LOCKED].includes(params.status)) {
            return new CommonResponseDto(ResCode.ERROR, '状态值设置错误')
        }
        if (!params.userId) {
            return new CommonResponseDto(ResCode.ERROR, '缺少参数')
        }
        try {
            const result = await this.userListService.editStatus(params.userId, params.status)
            if (result) {
                return new CommonResponseDto(ResCode.OK, 'success')
            }
            return new CommonResponseDto(ResCode.ERROR, '更新失败')
        } catch(e){
            return new CommonResponseDto(ResCode.ERROR, '更新异常')
        }
    }

    @Get('/model-list')
    async getModelList(@Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        const list = getModelConfigList(false)
        return new CommonResponseDto(ResCode.OK, 'success', list)
    }

    @Post('/login')
    async login(@Body() params: {userAccount: string, userPassword: string}, @Res({ passthrough: true }) res: Response) {
        res.status(HttpStatus.OK);
        if (!params.userAccount || !params.userPassword) {
            return new CommonResponseDto(ResCode.ERROR, '缺少参数')
        }
        try {
            const existUser = await this.userListService.getOneByAccountAndPassword(params.userAccount, params.userPassword)
            if (existUser) {
                const token = encrypt(existUser.userId + '_'+uuid(16), AppConfig.ManageSecretKey)
                await this.commonRedisService.set(AppConfig.ManageHeaderKey + '_' + existUser.userId, token, AppConfig.ManageTokenExpireSec)
                return new CommonResponseDto(ResCode.OK, 'success', {
                    user: {
                        userId: existUser.userId,
                        userAccount: existUser.userAccount,
                        contact: existUser.contact,
                        remark: existUser.remark,
                        createDate: existUser.createDate,
                        balance: existUser.balance,
                        status: existUser.status,
                    },
                    token,
                })
            }
            return new CommonResponseDto(ResCode.ERROR, '用户名或密码错误')
        } catch(e){
            return new CommonResponseDto(ResCode.ERROR, '登录异常')
        }
    }
}
